package com.alkaid.anime.service.impl;

import com.alibaba.fastjson.JSON;
import com.alkaid.anime.mapper.AnimeMapper;
import com.alkaid.anime.mapper.CollectMapper;
import com.alkaid.anime.service.CollectService;
import com.alkaid.anime.utils.RedisUtils;
import com.alkaid.commons.core.CacheKeyDefinition;
import com.alkaid.commons.entity.Anime;
import com.alkaid.commons.entity.Collect;
import com.alkaid.commons.ex.UnknownErrorException;
import com.alkaid.commons.utils.SnowflakeIdWorker;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * @author Kylin
 */
@Service
@Slf4j
public class CollectServiceImpl implements CollectService {

    private final CollectMapper collectMapper;

    private final AnimeMapper animeMapper;

    private final RedisUtils redisUtils;

    public CollectServiceImpl(CollectMapper collectMapper, AnimeMapper animeMapper, RedisUtils redisUtils) {
        this.collectMapper = collectMapper;
        this.animeMapper = animeMapper;
        this.redisUtils = redisUtils;
    }

    @Override
    public Boolean getCollect(Collect select) throws UnknownErrorException {
        // 获取key
        String key = CacheKeyDefinition.getCollectKey(select.getUserId(), select.getAnimeId());
        // 从缓存中查询
        Boolean result = (Boolean) redisUtils.getFromRedis(key);
        // 如果缓存中没有则从数据库查询
        if (result == null) {
            Collect collect = getCollectBySelect(select);
            if (collect == null) {
                return false;
            }
            result = collect.getIsDeleted() == 0;
            redisUtils.save2Redis(key, result, CacheKeyDefinition.CACHE_TIME_DAY);
        }
        return result;
    }

    @Override
    public void setCollect(Collect select) throws UnknownErrorException {
        Collect collect = getCollectBySelect(select);
        String key = CacheKeyDefinition.getCollectKey(select.getUserId(), select.getAnimeId());
        Long userId = select.getUserId();
        if (collect == null) {
            SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 3);
            select.setId(idWorker.nextId());
            select.setIsDeleted(0);
            Integer result = collectMapper.insert(select);
            if (result < 1) {
                throw new UnknownErrorException("点赞失败");
            }
            redisUtils.save2Redis(key, true, CacheKeyDefinition.CACHE_TIME_DAY);
            return;
        }
        int isDeleted = collect.getIsDeleted() == 0 ? 1 : 0;
        collect.setIsDeleted(isDeleted);
        collect.setUserId(null);
        collect.setAnimeId(null);
        Integer result = collectMapper.updateById(collect);
        if (result < 1) {
            throw new UnknownErrorException(isDeleted == 0 ? "追番失败" : "取消追番失败");
        }
        String key1 = CacheKeyDefinition.getCollectListKey(userId);
        boolean deleted = redisUtils.deleteKey(key1);
        log.info("删除追番列表：" + deleted);
        redisUtils.save2Redis(key, isDeleted == 0, CacheKeyDefinition.CACHE_TIME_DAY);
    }

    @Override
    public List<Anime> getCollectList(Long userId) {
        String key = CacheKeyDefinition.getCollectListKey(userId);
        List<Anime> animeList = JSON.parseArray(JSON.toJSONString(redisUtils.getFromRedis(key)), Anime.class);
        if (animeList == null || animeList.size() == 0) {
            animeList = animeMapper.findCollectList(userId);
            if (animeList == null || animeList.size() == 0) {
                return null;
            }
            redisUtils.save2Redis(key, animeList, CacheKeyDefinition.CACHE_TIME_WEEK);
        }
        return animeList;
    }

    private Collect getCollectBySelect(Collect select) {
        HashMap<SFunction<Collect, ?>, Object> map = new HashMap<>();
        map.put(Collect::getUserId, select.getUserId());
        map.put(Collect::getAnimeId, select.getAnimeId());
        return collectMapper.selectOne(new LambdaQueryWrapper<Collect>().allEq(map));
    }
}
